﻿namespace Pottery.Module.Infrastructure.Models
{
    using System;
    using System.Data.SqlTypes;
    using System.Runtime.Serialization;
    using Model.Infrastructure;

    /// <summary>
    /// Product.
    /// </summary>
    [DataContract]
    public class Product : IValidatable, IAssignable, INullable
    {
        #region Constructors

        /// <summary>
        /// Constructor with params. Creates a new Product. 
        /// </summary>
        /// <param name="marking">Articule</param>
        /// <param name="type">Type of the product</param>
        /// <param name="glayType">Type of glay</param>
        /// <param name="size">Size</param>
        /// <param name="price">Price per unit</param>
        /// <param name="printedImageLink">URL of the image example that need to be printed.</param>
        /// <param name="producingTime">Time to produce for one unit</param>
        public Product(string marking, string name, Enumerators.Type type, Enumerators.Material glayType, Size size,
            double price, string printedImageLink, DateTime producingTime, string instrictions, double manufactiringCost, bool showInCatalog)
        {
            m_Marking = marking;
            m_Name = name;
            m_Type = type;
            m_GlayType = glayType;
            m_Size = size;
            m_Price = price;
            m_PrintedImageLink = printedImageLink;
            m_ProducingTime = producingTime;
            m_ManufacturingCost = manufactiringCost;
            m_Instruction = instrictions;
            m_ShowInCatalog = showInCatalog;
        }

        /// <summary>
        /// Default constructor. Creates a Product with default params.
        /// </summary>
        public Product() { }

        #endregion

        #region Properties
        /// <summary>
        /// Articule of the product.
        /// </summary>
        [DataMember(Order = 1)]
        public string Marking
        {
            get { return m_Marking; }
            set
            {
                if (!IsNull)
                    m_Marking = value;
            }
        }

        [DataMember(Order = 2)]
        public string Name
        {
            get { return m_Name; }
            set
            {
                if (!IsNull)
                    m_Name = value;
            }
        }

        /// <summary>
        /// Type of the product.
        /// (Cup, Plate, Spoon, Custom)
        /// </summary>
        [DataMember(Order = 3)]
        public Enumerators.Type Type
        {
            get { return m_Type; }
            set
            {
                if (!IsNull)
                    m_Type = value;
            }
        }

        /// <summary>
        /// Glay type
        /// (RedGlay, WhiteGlay)
        /// </summary>
        [DataMember(Order = 4)]
        public Enumerators.Material GlayType
        {
            get { return m_GlayType; }
            set
            {
                if (!IsNull)
                    m_GlayType = value;
            }
        }

        /// <summary>
        /// Size of the product.
        /// </summary>
        [DataMember(Order = 5)]
        public Size Size
        {
            get { return m_Size; }
            set
            {
                if (!IsNull)
                    m_Size = value;
            }
        }

        /// <summary>
        /// Price per unit.
        /// </summary>
        [DataMember(Order = 7)]
        public double Price
        {
            get { return m_Price; }
            set
            {
                if (!IsNull)
                    m_Price = value;
            }
        }

        /// <summary>
        /// Manufacture cost
        /// </summary>
        [DataMember(Order = 6)]
        public double ManufactureCost
        {
            get { return m_ManufacturingCost; }
            set
            {
                if (!IsNull)
                    m_ManufacturingCost = value;
            }
        }

        /// <summary>
        /// URL of the image example that need to be printed.
        /// </summary>
        [DataMember(Order = 8)]
        public string PrintedImageLink
        {
            get { return m_PrintedImageLink; }
            set
            {
                if (!IsNull)
                    m_PrintedImageLink = value;
            }
        }

        /// <summary>
        /// Producing time per unit
        /// </summary>
        [DataMember(Order = 9)]
        public DateTime ProducingTime
        {
            get { return m_ProducingTime; }
            set
            {
                if (!IsNull)
                    m_ProducingTime = value;
            }
        }

        /// <summary>
        /// Producing Instructions
        /// </summary>
        [DataMember(Order = 10)]
        public string Instruction
        {
            get { return m_Instruction; }
            set
            {
                if (!IsNull)
                    m_Instruction = value;
            }
        }

        /// <summary>
        /// ShowInCatalog
        /// </summary>
        [DataMember(Order = 11)]
        public bool ShowInCatalog
        {
            get { return m_ShowInCatalog; }
            set
            {
                if (!IsNull)
                    m_ShowInCatalog = value;
            }
        }

        #endregion

        #region IValidate implementation

        /// <summary>
        /// Checks instance for data`s validity
        /// </summary>
        /// <returns>checking result</returns>
        public bool Validate()
        {
            bool isValid = true;

            if (string.IsNullOrEmpty(m_Marking) || string.IsNullOrWhiteSpace(m_Marking))
                isValid = false;

            return isValid;
        }

        #endregion

        #region IAssignable implementation

        /// <summary>
        /// Copy data from current object to object in param.
        /// </summary>
        /// <param name="obj">object to change </param>
        public void AssignTo(object obj)
        {
            if (IsNull)
                throw new InvalidOperationException();

            if (obj == null)
                throw new ArgumentNullException("obj");

            if (obj is Product)
            {
                Product prod = obj as Product;

                prod.m_Marking = m_Marking;
                prod.m_Type = m_Type;
                prod.m_GlayType = m_GlayType;
                prod.m_Size = m_Size;
                prod.m_Price = m_Price;
                prod.m_PrintedImageLink = m_PrintedImageLink;
                prod.m_ProducingTime = m_ProducingTime;
                prod.m_Instruction = m_Instruction;
                prod.m_ManufacturingCost = m_ManufacturingCost;
                prod.m_Name = m_Name;
                prod.m_ShowInCatalog = m_ShowInCatalog;

                prod.m_Null = false;

                return;
            }

            throw new NotSupportedException("Not supported type!");
        }

        #endregion

        #region INullable implementation

        public bool IsNull
        {
            get { return m_Null; }
        }

        public static Product Null
        {
            get
            {
                Product prod = new Product();
                prod.m_Null = true;
                return prod;
            }
        }

        #endregion

        #region Private Fields

        private string m_Marking = default(string);
        private string m_Name = default(string);
        private Enumerators.Material m_GlayType = Enumerators.Material.RedArgil;
        private Enumerators.Type m_Type = Enumerators.Type.Cup;
        private string m_PrintedImageLink = default(string);
        private DateTime m_ProducingTime = default(DateTime);
        private double m_Price = default(double);
        private Size m_Size = new Size();
        private double m_ManufacturingCost = default(double);
        private string m_Instruction = default(string);
        private bool m_ShowInCatalog = false;
        private bool m_Null = false;

        #endregion
    }
}
